package com.example.datamanage.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.datamanage.common.CodeEnum;
import com.example.datamanage.common.Result;
import com.example.datamanage.config.DynamicDataSource;
import com.example.datamanage.exception.MyException;
import com.example.datamanage.mapper.DataMapper;
import com.example.datamanage.pojo.Connect;
import com.example.datamanage.pojo.dto.DataSourceDTO;
import com.example.datamanage.pojo.dto.SearchDTO;
import com.example.datamanage.service.ConnectService;
import com.example.datamanage.mapper.ConnectMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
* @author 28142
* @description 针对表【connect(连接表)】的数据库操作Service实现
* @createDate 2023-07-24 16:57:23
*/
@Service
public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect>
    implements ConnectService{
    @Autowired
    private ConnectMapper connectMapper;
    @Autowired
    private DataMapper dataMapper;
    @Autowired
    private DynamicDataSource dynamicDataSource;

    @Override
    public Result findPage(Integer pageNum, Integer pageSize, SearchDTO searchDTO) {
        String name = searchDTO.getName();
        String dataType = searchDTO.getDataType();
        String dataName = searchDTO.getDataName();
        // 查询条件
        LambdaQueryWrapper<Connect> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StrUtil.isNotBlank(name), Connect::getName, name)
                .eq(StrUtil.isNotBlank(dataType), Connect::getDataType, dataType)
                .like(StrUtil.isNotBlank(dataName), Connect::getDataName, dataName);
        Page<Connect> page = new Page<>(pageNum, pageSize);
        page.setOptimizeCountSql(false);
        return Result.success(connectMapper.selectPage(page, wrapper));
    }

    @Override
    public boolean saveConn(Connect connect) {
        // 将实体类的属性拷贝到DTO中
        DataSourceDTO dataSourceDTO = new DataSourceDTO();
        BeanUtils.copyProperties(connect, dataSourceDTO);
        // 测试连接，连接不上提示，连接成功再继续执行
        if (!testConn(dataSourceDTO)) {
            throw new MyException(CodeEnum.CODE_501.getCode(), "数据源错误");
        }
        // 如果id为空，表示添加；否则修改
        if (connect.getId() == null) {
            // 查询数据库，如果数据库类型、数据库名和ip都一致，就认为已经有记录
            LambdaQueryWrapper<Connect> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Connect::getDataType, connect.getDataType())
                    .eq(Connect::getDataName, connect.getDataName())
                    .eq(Connect::getUrl, connect.getUrl());
            Connect conn = getOne(wrapper);
            // 如果已有记录 提示数据源已存在
            if (conn != null) {
                throw new MyException(CodeEnum.CODE_400.getCode(), "数据源已存在");
            }
            // 添加数据
            return save(connect);
        } else {
            // 设置修改时间
            connect.setUpdateTime(new Date());
            // 修改数据
            return update(connect, null);
        }
        // return saveOrUpdate(connect);
    }

    /**
     * 切换数据源
     * @author 杨雨盛
     * @date 2023/7/25 13:37
     * @param dataSourceDTO
     * @return boolean
     */
    @Override
    public boolean createConn(DataSourceDTO dataSourceDTO) throws NoSuchFieldException, IllegalAccessException {
        // 清空数据源
        DynamicDataSource.clearDataSource();
        // 创建并切换数据源
        return dynamicDataSource.createDataSource(dataSourceDTO);
    }

    /**
     * 测试数据源
     * @author 杨雨盛
     * @date 2023/7/25 13:38
     * @param dataSourceDTO
     * @return boolean
     */
    @Override
    public boolean testConn(DataSourceDTO dataSourceDTO) {
        return dynamicDataSource.testDataSource(dataSourceDTO);
    }

    @Override
    public Result getNameByDataType(String dataType) {
        LambdaQueryWrapper<Connect> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(Connect::getName)
                .eq(Connect::getDataType, dataType);
        return Result.success(listObjs(wrapper));
    }

    @Override
    public Result getDataNameByDataTypeAndName(String dataType, String name) {
        LambdaQueryWrapper<Connect> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(Connect::getDataName)
                .eq(Connect::getDataType, dataType)
                .eq(Connect::getName, name);
        return Result.success(listObjs(wrapper));
    }

    @Override
    public Result getConn(SearchDTO searchDTO) {
        String dataType = searchDTO.getDataType();
        String name = searchDTO.getName();
        String dataName = searchDTO.getDataName();
        // 查询条件
        LambdaQueryWrapper<Connect> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Connect::getDataType, dataType)
                .eq(Connect::getName, name)
                .eq(Connect::getDataName, dataName);
        Connect one = getOne(wrapper);
        if (one == null) {
            return Result.error(CodeEnum.CODE_500.getCode(), CodeEnum.CODE_500.getMsg());
        }
        return Result.success(one);
    }

    @Override
    public Result switchDatasource(String dataType, String name) throws NoSuchFieldException, IllegalAccessException {
        // 查询数据源对象
        LambdaQueryWrapper<Connect> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Connect::getDataType, dataType)
                .eq(Connect::getName, name);
        Connect connect = getOne(wrapper);
        // 如果不为空，切换数据源
        if (connect != null) {
            DataSourceDTO dataSourceDTO = new DataSourceDTO();
            BeanUtils.copyProperties(connect, dataSourceDTO);
            // 切换成功，将数据返回
            if (createConn(dataSourceDTO)) {
                // Map<String, Object> map = new HashMap<>();
                // // 表集合
                // List<LinkedHashMap<String, String>> tables = dataMapper.showTables(connect.getDataName());
                // // 视图集合
                // List<LinkedHashMap<String, String>> views = dataMapper.showViews(connect.getDataName());
                // // 合并两个集合
                // List list = new ArrayList();
                // list.addAll(tables);
                // list.addAll(views);
                // // 将数据库名、表个数、视图个数和表集合放入map
                // map.put("dataName", connect.getDataName());
                // map.put("tableLen", tables.size());
                // map.put("viewLen", views.size());
                // map.put("list", list);
                // System.out.println(map);
                return Result.success(connect.getDataName());
            }
            throw new MyException(CodeEnum.CODE_501.getCode(), "切换数据源失败");
        }
        throw new MyException(CodeEnum.CODE_501.getCode(), "数据源不存在");
    }
}




